import numpy
import math

class Vector(object):
    __slots__ = ('xyz')
    
    def __init__(self, x = 0.0, y = 0.0, z = 0.0):
        self.xyz = numpy.array([x, y, z])

    def __getitem__(self, index):
        return self.xyz[index]

    def __setitem__(self, index, value):
        self.xyz[index] = value

    def __repr__(self):
        return '[%f %f %f]' % (self.xyz[0], self.xyz[1], self.xyz[2])

    def __eq__(self, other):
        return (self.xyz == other.xyz).all()

    def __ne__(self, other):
        return (self.xyz != other.xyz).any()

    def __add__(self, other):
        return Vector(self[0] + other[0], self[1] + other[1], self[2] + other[2])

    def __iadd__(self, other):
        self = self + other
        return self

    def __sub__(self, other):
        return Vector(self[0] - other[0], self[1] - other[1], self[2] - other[2])

    def __isub__(self, other):
        self = self - other
        return self

    def __mul__(self, scale):
        return Vector(self[0] * scale, self[1] * scale, self[2] * scale)

    def __imul__(self, scale):
        self = self * scale
        return self

    def __rmul__(self, scale):
        return self * scale
    
    def __div__(self, scale):
        return Vector(self[0] / scale, self[1] / scale, self[2] / scale)

    def __idiv__(self, scale):
        self = self / scale
        return self

    def __neg__(self):
        return Vector(-self[0], -self[1], -self[2])

    def Length(self):
        return math.sqrt((self.xyz ** 2).sum())

    def LengthSquared(self):
        return (self.xyz ** 2).sum()

    def Normalize(self):
        return self / self.Length()

def Dot(v1, v2):
    return numpy.dot(v1.xyz, v2.xyz)

def Cross(v1, v2):
    result = Vector()
    result.xyz = numpy.cross(v1.xyz, v2.xyz)
    return result
